import java.util.Arrays;
import java.util.Scanner;

/**
 * Arrays and Strings Examples
 * This class demonstrates various operations on arrays and strings in Java
 */
public class ArraysAndStrings {
    
    public static void main(String[] args) {
        ArraysAndStrings example = new ArraysAndStrings();
        
        // Demonstrating array operations
        example.demonstrateOneDimensionalArrays();
        example.demonstrateMultidimensionalArrays();
        example.demonstrateArrayTraversal();
        example.demonstrateArraysUtilityClass();
        example.demonstrateArrayAlgorithms();
        
        // Demonstrating string operations
        example.demonstrateStringClass();
        example.demonstrateStringBufferAndBuilder();
        example.demonstrateStringComparison();
        example.demonstrateRegularExpression();
        example.demonstrateStringProcessing();
    }
    
    /**
     * Method to demonstrate one-dimensional arrays
     */
    public void demonstrateOneDimensionalArrays() {
        System.out.println("=== One-Dimensional Arrays ===");
        
        // Declaration and initialization
        int[] numbers; // Declaration
        numbers = new int[5]; // Creation
        
        // Initialize with values
        int[] scores = {85, 90, 78, 92, 88};
        
        // Initialize using new keyword
        String[] names = new String[]{"Alice", "Bob", "Charlie", "David", "Eve"};
        
        // Accessing array elements
        System.out.println("First score: " + scores[0]);
        System.out.println("Last name: " + names[names.length - 1]);
        
        // Modifying array elements
        numbers[0] = 10;
        numbers[1] = 20;
        numbers[2] = 30;
        numbers[3] = 40;
        numbers[4] = 50;
        
        System.out.println("Numbers array: " + Arrays.toString(numbers));
        System.out.println();
    }
    
    /**
     * Method to demonstrate multidimensional arrays
     */
    public void demonstrateMultidimensionalArrays() {
        System.out.println("=== Multidimensional Arrays ===");
        
        // Two-dimensional array declaration and initialization
        int[][] matrix = new int[3][3];
        
        // Initialize with values
        int[][] grades = {
            {85, 90, 78},
            {92, 88, 95},
            {76, 81, 89}
        };
        
        // Accessing elements
        System.out.println("Element at row 1, column 2: " + grades[1][2]);
        
        // Initializing elements
        matrix[0][0] = 1;
        matrix[0][1] = 2;
        matrix[0][2] = 3;
        matrix[1][0] = 4;
        matrix[1][1] = 5;
        matrix[1][2] = 6;
        matrix[2][0] = 7;
        matrix[2][1] = 8;
        matrix[2][2] = 9;
        
        // Printing 2D array
        System.out.println("Matrix:");
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }
    
    /**
     * Method to demonstrate array traversal
     */
    public void demonstrateArrayTraversal() {
        System.out.println("=== Array Traversal ===");
        
        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        
        // Using traditional for loop
        System.out.print("Using for loop: ");
        for (int i = 0; i < numbers.length; i++) {
            System.out.print(numbers[i] + " ");
        }
        System.out.println();
        
        // Using enhanced for loop (for-each)
        System.out.print("Using for-each loop: ");
        for (int num : numbers) {
            System.out.print(num + " ");
        }
        System.out.println();
        
        // Traversing 2D array
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        System.out.println("Traversing 2D array:");
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }
    
    /**
     * Method to demonstrate Arrays utility class
     */
    public void demonstrateArraysUtilityClass() {
        System.out.println("=== Arrays Utility Class ===");
        
        int[] numbers = {5, 2, 8, 1, 9, 3};
        String[] names = {"Charlie", "Alice", "Bob", "David"};
        
        System.out.println("Original array: " + Arrays.toString(numbers));
        
        // Sorting
        Arrays.sort(numbers);
        System.out.println("Sorted numbers: " + Arrays.toString(numbers));
        
        Arrays.sort(names);
        System.out.println("Sorted names: " + Arrays.toString(names));
        
        // Searching (binary search requires sorted array)
        int index = Arrays.binarySearch(numbers, 8);
        System.out.println("Index of 8 in sorted array: " + index);
        
        // Filling array
        int[] filledArray = new int[5];
        Arrays.fill(filledArray, 7);
        System.out.println("Filled array: " + Arrays.toString(filledArray));
        
        // Comparing arrays
        int[] array1 = {1, 2, 3};
        int[] array2 = {1, 2, 3};
        int[] array3 = {3, 2, 1};
        
        System.out.println("Array1 equals Array2: " + Arrays.equals(array1, array2));
        System.out.println("Array1 equals Array3: " + Arrays.equals(array1, array3));
        System.out.println();
    }
    
    /**
     * Method to demonstrate array algorithms
     */
    public void demonstrateArrayAlgorithms() {
        System.out.println("=== Array Algorithms ===");
        
        int[] numbers = {64, 34, 25, 12, 22, 11, 90};
        System.out.println("Original array: " + Arrays.toString(numbers));
        
        // Bubble sort implementation
        bubbleSort(numbers.clone());
        
        // Find maximum element
        int[] array = {3, 5, 7, 2, 8, 1};
        int max = findMax(array);
        System.out.println("Maximum element in " + Arrays.toString(array) + " is: " + max);
        
        // Linear search
        int target = 7;
        int foundIndex = linearSearch(array, target);
        System.out.println("Index of " + target + " in array: " + foundIndex);
        System.out.println();
    }
    
    /**
     * Bubble sort implementation
     */
    public void bubbleSort(int[] arr) {
        int n = arr.length;
        System.out.println("Sorting using Bubble Sort:");
        System.out.println("Before sorting: " + Arrays.toString(arr));
        
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    // Swap elements
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        
        System.out.println("After sorting: " + Arrays.toString(arr));
    }
    
    /**
     * Method to find maximum element in array
     */
    public int findMax(int[] arr) {
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }
    
    /**
     * Linear search implementation
     */
    public int linearSearch(int[] arr, int target) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == target) {
                return i;
            }
        }
        return -1; // Element not found
    }
    
    /**
     * Method to demonstrate String class features and methods
     */
    public void demonstrateStringClass() {
        System.out.println("=== String Class ===");
        
        // Creating strings
        String str1 = "Hello";
        String str2 = new String("World");
        String str3 = "Hello";
        
        System.out.println("str1: " + str1);
        System.out.println("str2: " + str2);
        System.out.println("str3: " + str3);
        
        // String length
        System.out.println("Length of str1: " + str1.length());
        
        // Character at specific index
        System.out.println("Character at index 1 in str1: " + str1.charAt(1));
        
        // Substring
        System.out.println("Substring of str1 from index 2: " + str1.substring(2));
        System.out.println("Substring of str1 from index 1 to 4: " + str1.substring(1, 4));
        
        // Concatenation
        String combined = str1 + " " + str2;
        System.out.println("Combined string: " + combined);
        
        // String comparison
        System.out.println("str1 equals str3: " + str1.equals(str3));
        System.out.println("str1 == str3: " + (str1 == str3));
        
        // Case conversion
        String text = "Java Programming";
        System.out.println("Original text: " + text);
        System.out.println("Uppercase: " + text.toUpperCase());
        System.out.println("Lowercase: " + text.toLowerCase());
        
        // Finding index
        System.out.println("Index of 'gram' in '" + text + "': " + text.indexOf("gram"));
        System.out.println();
    }
    
    /**
     * Method to demonstrate StringBuffer and StringBuilder
     */
    public void demonstrateStringBufferAndBuilder() {
        System.out.println("=== StringBuffer and StringBuilder ===");
        
        // StringBuffer (thread-safe)
        StringBuffer stringBuffer = new StringBuffer("Hello");
        System.out.println("Original StringBuffer: " + stringBuffer);
        
        stringBuffer.append(" World");
        System.out.println("After append: " + stringBuffer);
        
        stringBuffer.insert(5, ",");
        System.out.println("After insert: " + stringBuffer);
        
        stringBuffer.reverse();
        System.out.println("After reverse: " + stringBuffer);
        
        // StringBuilder (not thread-safe, but faster)
        StringBuilder stringBuilder = new StringBuilder("Java");
        System.out.println("\nOriginal StringBuilder: " + stringBuilder);
        
        stringBuilder.append(" is");
        stringBuilder.append(" awesome");
        System.out.println("After appends: " + stringBuilder);
        
        stringBuilder.replace(0, 4, "Python");
        System.out.println("After replace: " + stringBuilder);
        System.out.println();
    }
    
    /**
     * Method to demonstrate string comparison and operations
     */
    public void demonstrateStringComparison() {
        System.out.println("=== String Comparison and Operations ===");
        
        String str1 = "Hello";
        String str2 = "Hello";
        String str3 = new String("Hello");
        String str4 = "hello";
        
        // Using == operator
        System.out.println("str1 == str2: " + (str1 == str2)); // true (string pool)
        System.out.println("str1 == str3: " + (str1 == str3)); // false (different objects)
        
        // Using equals() method
        System.out.println("str1.equals(str2): " + str1.equals(str2)); // true
        System.out.println("str1.equals(str3): " + str1.equals(str3)); // true
        System.out.println("str1.equals(str4): " + str1.equals(str4)); // false
        
        // Using equalsIgnoreCase() method
        System.out.println("str1.equalsIgnoreCase(str4): " + str1.equalsIgnoreCase(str4)); // true
        
        // String operations
        String text = "  Java Programming  ";
        System.out.println("Original text: '" + text + "'");
        System.out.println("Trimmed text: '" + text.trim() + "'");
        
        String[] words = text.trim().split(" ");
        System.out.println("Split words:");
        for (String word : words) {
            if (!word.isEmpty()) {
                System.out.println("  " + word);
            }
        }
        System.out.println();
    }
    
    /**
     * Method to demonstrate regular expressions
     */
    public void demonstrateRegularExpression() {
        System.out.println("=== Regular Expressions ===");
        
        String email = "user@example.com";
        String phone = "123-456-7890";
        String text = "The price is $25.99 for 3 items.";
        
        // Email validation
        String emailRegex = "^[A-Za-z0-9+_.-]+@([A-Za-z0-9.-]+\\.[A-Za-z]{2,})$";
        System.out.println("Email '" + email + "' is valid: " + email.matches(emailRegex));
        
        // Phone number validation
        String phoneRegex = "\\d{3}-\\d{3}-\\d{4}";
        System.out.println("Phone '" + phone + "' is valid: " + phone.matches(phoneRegex));
        
        // Find digits in text
        String digitRegex = "\\d+";
        String[] numbers = text.split("\\D+"); // Split by non-digits
        System.out.println("Numbers found in text '" + text + "':");
        for (String number : numbers) {
            if (!number.isEmpty()) {
                System.out.println("  " + number);
            }
        }
        System.out.println();
    }
    
    /**
     * Method to demonstrate string processing techniques
     */
    public void demonstrateStringProcessing() {
        System.out.println("=== String Processing Techniques ===");
        
        // Formatting strings
        String name = "Alice";
        int age = 25;
        double salary = 50000.50;
        
        String formatted = String.format("Name: %s, Age: %d, Salary: $%.2f", name, age, salary);
        System.out.println(formatted);
        
        // Joining strings
        String[] fruits = {"Apple", "Banana", "Orange"};
        String joined = String.join(", ", fruits);
        System.out.println("Joined fruits: " + joined);
        
        // Replacing text
        String sentence = "The quick brown fox jumps over the lazy dog";
        String replaced = sentence.replace("the", "THE");
        System.out.println("Original: " + sentence);
        System.out.println("Replaced: " + replaced);
        
        // Checking string content
        String emptyString = "";
        String blankString = "   ";
        String normalString = "Hello";
        
        System.out.println("Empty string is empty: " + emptyString.isEmpty());
        System.out.println("Blank string is empty: " + blankString.isEmpty());
        System.out.println("Blank string is blank: " + blankString.isBlank());
        System.out.println("Normal string starts with 'H': " + normalString.startsWith("H"));
        System.out.println("Normal string ends with 'o': " + normalString.endsWith("o"));
        System.out.println();
    }
}